﻿using System;
using System.Collections.Generic;
using Autodesk.Revit.DB;
using YJKArchUtils.Utils;
using YJKRevitDimensionText.OneKeyPlanDim.Utility;

namespace YJKRevitDimensionText.OneKeyPlanDim.DimData
{
	public class DbBarrierFreeRamp : DbDimBase
	{
		public DbBarrierFreeRamp(Group group)
		{
			this.m_Group = group;
		}

		public Line SlopeStartLine
		{
			get
			{
				return this.m_SlopeStartLine;
			}
		}

		public bool AnalysisInfo()
		{
			if (!base.IsNeedAnalysisInfo())
			{
				return true;
			}
			try
			{
				this.m_lstFloor = this.GetlstFloorFromGroup();
				if (!this.GetStartBasePlanarFace(this.m_lstFloor))
				{
					return false;
				}
				this.CalSlopeValue();
				List<CurveLoop> list = new List<CurveLoop>();
				foreach (Floor floor in this.m_lstFloor)
				{
					foreach (CurveLoop curveLoop in GeometryHelper.GetMaxAreaFaceFromFloor(floor).GetEdgesAsCurveLoops())
					{
						CurveLoop xyplaneCurve = CommonInterface.GetXYPlaneCurve(curveLoop);
						list.Add(xyplaneCurve);
					}
				}
				OcclusionArea.GetInstance().AddRampCurve(this.m_Group.Id, list);
			}
			catch
			{
				return false;
			}
			return !(this.m_SlopeStartLine == null);
		}

		public override bool CreateSizeDim(Autodesk.Revit.DB.Document doc)
		{
			return base.CreateSizeDim(doc) && this.AnalysisInfo();
		}

		public override bool CreateLevelDim(Autodesk.Revit.DB.Document doc, out List<SingleLevelDimDataInfo> lstSingleLevelDimDataInfo)
		{
			if (!base.CreateLevelDim(doc, out lstSingleLevelDimDataInfo))
			{
				return false;
			}
			if (!this.AnalysisInfo())
			{
				return false;
			}
			XYZ xyz = (this.SlopeStartLine.GetEndPoint(0) + this.SlopeStartLine.GetEndPoint(1)) / 2.0 - this.m_SlopeDimDir * (Common.MMToFeet(1500.0) * (double)this.m_doc.ActiveView.Scale / 100.0);
			if (base.ComponentInSlopePlanarFace != null)
			{
				xyz = CommonInterface.PtInPlanarFaceInDir(xyz, base.ComponentInSlopePlanarFace, XYZ.BasisZ);
			}
			FamilyInstance familyInstance = new LevelDimData(this.m_doc)
			{
				PtDimLocation = xyz,
				DimVal = base.FloorLevelVal
			}.CreateLevelDim();
			AnnotationSymbol annotationSymbol = null;
			if (familyInstance != null)
			{
				annotationSymbol = (familyInstance as AnnotationSymbol);
			}
			if (annotationSymbol != null)
			{
				SingleLevelDimDataInfo singleLevelDimDataInfo = new SingleLevelDimDataInfo(annotationSymbol);
				if (base.ComponentInSlopePlanarFace != null)
				{
					singleLevelDimDataInfo.LevelVal = xyz.Z;
				}
				else
				{
					singleLevelDimDataInfo.LevelVal = base.dFloorLevelVal;
				}
				singleLevelDimDataInfo.LadderLineLength = this.SlopeStartLine.Length;
				singleLevelDimDataInfo.DimDir = this.SlopeStartLine.Direction;
				singleLevelDimDataInfo.PtLocation = xyz;
				singleLevelDimDataInfo.bStepDownDim = false;
				lstSingleLevelDimDataInfo.Add(singleLevelDimDataInfo);
			}
			return true;
		}

		public override bool CreateSlopeDim(Autodesk.Revit.DB.Document doc)
		{
			if (!base.CreateSlopeDim(doc))
			{
				return false;
			}
			if (!this.AnalysisInfo())
			{
				return false;
			}
			if (this.m_SlopeStartLine == null)
			{
				return false;
			}
			XYZ ptStart = (this.m_SlopeStartLine.GetEndPoint(0) + this.m_SlopeStartLine.GetEndPoint(1)) / 2.0;
			FamilyInstance familyInstance = new SlopeDimData(this.m_doc)
			{
				PtStart = ptStart,
				SlopeDimDir = this.m_SlopeDimDir.Normalize(),
				DimVal = this.m_strSlopeValue
			}.CreateSlopeDim();
			if (familyInstance == null)
			{
				return false;
			}
			base.SetSlopeOcclusionArea(familyInstance);
			return true;
		}

		private bool GetStartLineFromFloor(Floor floor, out double dHeightZ, out Line startLine, out XYZ slopeDimDir)
		{
			dHeightZ = double.MaxValue;
			slopeDimDir = XYZ.Zero;
			startLine = null;
			List<Line> list = new List<Line>();
			foreach (Curve curve in GeometryHelper.GetAllEdgeList(floor))
			{
				Line line = curve as Line;
				if (line != null && GeometryHelper.VectorVerticalVector(line.Direction, XYZ.BasisZ))
				{
					list.Add(line);
				}
			}
			double num = double.MaxValue;
			double num2 = double.MinValue;
			Line lineMaxHeight = startLine;
			foreach (Line line2 in list)
			{
				dHeightZ = (Geometry.LessThan(line2.GetEndPoint(0).Z, line2.GetEndPoint(1).Z) ? line2.GetEndPoint(1).Z : line2.GetEndPoint(0).Z);
				if (Geometry.LessThan(dHeightZ, num))
				{
					num = dHeightZ;
					startLine = line2;
				}
				if (Geometry.LessThan(num2, dHeightZ))
				{
					num2 = dHeightZ;
					lineMaxHeight = line2;
				}
			}
			return !(startLine == null) && this.GetSlopeUpDir(startLine, lineMaxHeight, out slopeDimDir);
		}

		private bool GetStartBasePlanarFace(List<Floor> lstFloor)
		{
			this.m_SlopeStartLine = null;
			double num = double.MaxValue;
			XYZ basisY = XYZ.BasisY;
			Floor thisElement = null;
			foreach (Floor floor in lstFloor)
			{
				Line slopeStartLine = null;
				double num2 = 0.0;
				if (this.GetStartLineFromFloor(floor, out num2, out slopeStartLine, out basisY) && Geometry.LessThan(num2, num))
				{
					num = num2;
					this.m_SlopeStartLine = slopeStartLine;
					this.m_SlopeDimDir = basisY;
					thisElement = floor;
				}
			}
			List<PlanarFace> list = GeometryHelper.PlanarFaceWithCommonLine(GeometryHelper.GetAllPlanarFace(thisElement), this.m_SlopeStartLine);
			if (list.Count != 2)
			{
				return false;
			}
			this.m_StartBasePlanarFace = ((list[0].Area > list[1].Area) ? list[0] : list[1]);
			return true;
		}

		private List<Floor> GetlstFloorFromGroup()
		{
			List<Floor> list = new List<Floor>();
			Document document = this.m_Group.Document;
			foreach (ElementId elementId in this.m_Group.GetMemberIds())
			{
				Element element = document.GetElement(elementId);
				if (element != null && element is Floor)
				{
					list.Add(element as Floor);
				}
			}
			return list;
		}

		private bool GetSlopeUpDir(Line line, Line lineMaxHeight, out XYZ slopeDir)
		{
			slopeDir = XYZ.Zero;
			if (lineMaxHeight == null || line == null)
			{
				return false;
			}
			XYZ xyz = (line.GetEndPoint(0) + line.GetEndPoint(1)) / 2.0;
			slopeDir = XYZ.BasisZ.CrossProduct(line.Direction).Normalize();
			XYZ xyz2 = xyz + slopeDir * Common.MMToFeet(100.0);
			if (Geometry.LessThan((xyz - slopeDir * Common.MMToFeet(100.0)).DistanceTo(lineMaxHeight.GetEndPoint(0)), xyz2.DistanceTo(lineMaxHeight.GetEndPoint(0))))
			{
				slopeDir = -slopeDir;
			}
			return true;
		}

		private void CalSlopeValue()
		{
			double num = this.m_StartBasePlanarFace.FaceNormal.AngleTo(XYZ.BasisZ);
			if (Geometry.LessThan(Math.PI*.5, num))
			{
				num = Math.PI - num;
			}
			double num2 = 1.0 / Math.Tan(num);
			int num3 = (int)num2;
			if (Geometry.IsEqual(num2, (double)num3))
			{
				this.m_strSlopeValue = num3.ToString();
			}
			else
			{
				this.m_strSlopeValue = num2.ToString("f2");
			}
			this.m_strSlopeValue = "1 : " + this.m_strSlopeValue;
		}

		private Group m_Group;

		private PlanarFace m_StartBasePlanarFace;

		private Line m_SlopeStartLine;

		private string m_strSlopeValue = string.Empty;

		private XYZ m_SlopeDimDir = XYZ.Zero;

		private List<Floor> m_lstFloor = new List<Floor>();
	}
}
